import axios, {
  AxiosRequestConfig,
  AxiosHeaders,
  Method,
  AxiosResponse,
} from 'axios';

interface RequestParams {
  url: string;
  params?: object;
  headers?: object;
  body?: object;
}

export class HttpClient {
  private static client = axios.create({
    timeout: 60 * 1000,
  });

  static {
    HttpClient.client.interceptors.request.use(
      (config: AxiosRequestConfig) => {
        // 创建一个 AxiosHeaders 实例，并设置需要的头部字段
        const headers = new AxiosHeaders();

        // 合并用户提供的 headers 和自定义的 headers
        if (config.headers) {
          Object.keys(config.headers).forEach((key) => {
            headers.set(key, config.headers[key]);
          });
        }

        // 更新配置中的 headers
        return {
          ...config,
          headers,
        };
      },
      (error) => Promise.reject(error),
    );

    HttpClient.client.interceptors.response.use(
      (response: any) => response,
      (error) => Promise.reject(error),
    );
  }

  static request<T>(
    method: Method,
    { url, params, headers, body }: RequestParams,
  ): Promise<T> {
    return HttpClient.client({
      method,
      url,
      data: body,
      params,
      headers,
    }).then((res: AxiosResponse<T>) => res.data);
  }

  static get<T>({ url, params, headers }: RequestParams): Promise<T> {
    return this.request<T>('get', { url, params, headers, body: undefined });
  }

  static post<T>({ url, params, body, headers }: RequestParams): Promise<T> {
    return this.request<T>('post', { url, params, headers, body });
  }

  static put<T>({ url, body, headers }: RequestParams): Promise<T> {
    return this.request<T>('put', { url, params: undefined, headers, body });
  }

  static delete<T>({ url, params, headers }: RequestParams): Promise<T> {
    return this.request<T>('delete', { url, params, headers, body: undefined });
  }

  static download({ url, params, headers }: RequestParams): Promise<Blob> {
    return HttpClient.client({
      method: 'GET',
      url,
      params,
      headers,
      responseType: 'blob',
    }).then((res) => res.data);
  }
}
